<template>
  <div id="menu">
    <div class="handbox">
      <div class="text">几何图形类型：</div>
      <div class="select">
        <el-select v-model="drawType" size="large" @change="handleTypeChange">
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
      </div>
    </div>
    <div id="map"></div>
  </div>
</template>
<script  setup>
import { onMounted, reactive, onBeforeUnmount, ref } from "vue";
import { Map, View } from "ol";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { XYZ, Vector as VectorSource } from "ol/source";
import { Style, Fill, Stroke, Circle } from "ol/style";
import { Draw } from "ol/interaction";
import { createRegularPolygon } from "ol/interaction/Draw";
import { Polygon } from "ol/geom";
import { MAPURL, ATTRIBUTIONS } from "../../constants";
const GraphType = {
  None: "None",
  Point: "Point",
  LineString: "LineString",
  Polygon: "Polygon",
  Circle: "Circle",
  Square: "Square",
  Box: "Box",
};
// Reactive state
const drawType = ref(GraphType.Point);

const options = ref([
  { label: "无", value: GraphType.None },
  { label: "点", value: GraphType.Point },
  { label: "线", value: GraphType.LineString },
  { label: "多边形", value: GraphType.Polygon },
  { label: "圆", value: GraphType.Circle },
  { label: "正方形", value: GraphType.Square },
  { label: "长方形", value: GraphType.Box },
]);
// Map variables
const map = ref(null);
const draw = ref(null);
const source = ref(new VectorSource({ wrapX: false }));
const vector = ref(
  new VectorLayer({
    source: source.value,
    style: new Style({
      fill: new Fill({
        color: "rgba(255, 255, 255, 0.2)",
      }),
      stroke: new Stroke({
        color: "#ff0000",
        width: 2,
      }),
      image: new Circle({
        radius: 7,
        fill: new Fill({
          color: "#ff0000",
        }),
      }),
    }),
  }),
);
const raster = ref(
  new TileLayer({
    source: new XYZ({
    //   attributions: ATTRIBUTIONS,
      url: MAPURL,
      maxZoom: 20,
    }),
  }),
);
// Initialize map
const initMap = () => {
  map.value = new Map({
    target: "map",
    layers: [raster.value],
    view: new View({
      projection: "EPSG:4326",
      center: [0, 0],
      zoom: 5,
    }),
  });
};
// Add drawing interaction
const addInteraction = () => {
  if (draw.value !== null) {
    map.value.removeInteraction(draw.value);
  }
  let value = drawType.value;
  if (value !== GraphType.None) {
    if (source.value === null) {
      source.value = new VectorSource({ wrapX: false });
      vector.value.setSource(source.value);
    }
    let geometryFunction, maxPoints;
    if (value === GraphType.Square) {
      value = GraphType.Circle;
      geometryFunction = createRegularPolygon(4);
    } else if (value === GraphType.Box) {
      value = GraphType.LineString;
      maxPoints = 2;
      geometryFunction = (coordinates, geometry) => {
        const start = coordinates[0];
        const end = coordinates[1];
        if (!geometry) {
          geometry = new Polygon([
            [start, [start[0], end[1]], end, [end[0], start[1]], start],
          ]);
        }
        geometry.setCoordinates([
          [start, [start[0], end[1]], end, [end[0], start[1]], start],
        ]);
        return geometry;
      };
    }
    draw.value = new Draw({
      source: source.value,
      type: value,
      geometryFunction: geometryFunction,
      maxPoints: maxPoints,
    });
    draw.value.on("drawend", e => {
      map.value.removeInteraction(draw.value);
    });
    map.value.addInteraction(draw.value);
  } else {
    source.value = null;
    vector.value.setSource(source.value);
  }
};
// Handle type change
const handleTypeChange = () => {
  addInteraction();
};
// Lifecycle hooks
onMounted(() => {
  initMap();
  map.value.addLayer(vector.value);
  addInteraction();
});
onBeforeUnmount(() => {
  if (map.value) {
    map.value.dispose();
    map.value = null;
  }
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang='scss'>
#menu {
  width: 100%;
  height: 100%;
  .handbox {
    display: flex;
    width: 500px;
    height: 40px;
    .text {
      width: 120px;
      line-height: 40px;
      color: #0ad3d6;
    }
    .select {
      width: 300px;
      height: 30px;
    }
  }
  #map {
    width: 100%;
    height: calc(100% - 40px);
  }
}
v-deep.el-select--large .el-select__wrapper {
  height: 30px;
}
</style>